home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / tex / lametex_.z / lametex_ / lametex / src / Operator.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-09-19  |  45.1 KB  |  728 lines

  1. /* Operator.C
  2.  *
  3.  * Some tokens like the curly braces have many meanings in many places.
  4.  * However, for most tokens there is a simple one-to-one mapping between
  5.  * the token and some operation to be performed. There are a number of
  6.  * common types of Operators, and then some special purpose ones.
  7.  *
  8.  * Copyright 1992 Jonathan Monsarrat. Permission given to freely distribute,
  9.  * edit and use as long as this copyright statement remains intact.
  10.  *
  11.  */
  12.  
  13. #include <string.h>
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <search.h>
  17. #include <time.h>
  18. #include <ctype.h>
  19. #include "Operator.h"
  20. #include "Global.h"
  21. #include "Counter.h"
  22. #include "Document.h"
  23. #include "Font.h"
  24. #include "Justify.h"
  25.  
  26. Operator::Operator(char *tokentext, int page_specific, int stealth,
  27.            int paramtype, int subtype, float value, char *replacestr,
  28.            void (*handle)(int, int, float, char *))
  29. {
  30.    _tokentext = tokentext;
  31.    _page_specific = page_specific;
  32.    _stealth = stealth;
  33.    _paramtype = paramtype;
  34.    _subtype = subtype;
  35.    _value = value;
  36.    _replacestr = replacestr;
  37.    _handle = handle;
  38.  
  39.    _valid = TRUE;
  40. }
  41.  
  42. Operator::Operator(const int array_ender)
  43. {
  44.    _valid = array_ender;   // Invalid operator marks the end of the array.
  45. }
  46.  
  47. /* A list of all the token versus their Operators. Some tokens like "\quote"
  48.  * have more than one Operator because they involve more than one simple
  49.  * parameter change, like a change to both leftmargin and textwidth.
  50.  * DO NOT USE M-x sort-lines TO SORT THIS! Some of the operators have multiple
  51.  * lines, which must be kept preserved in a certain order.
  52.  */
  53. static Operator operators[] =
  54. {
  55.    Operator("",                  0,0,0,                         0,                         0.0,  "",                  Operator::new_paragraph),    // handled
  56.    Operator("\\#",               1,0,0,                         0,                         0.0,  "#",                 Operator::replace),          // handled
  57.    Operator("\\$",               1,0,0,                         0,                         0.0,  "$",                 Operator::replace),          // handled
  58.    Operator("\\%",               1,0,Environment::PFont,        Font::FunnyPrint,          0.0,  "(%)",               Stack::set),                 // handled
  59.    Operator("\\&",               1,0,0,                         0,                         0.0,  "&",                 Operator::replace),          // handled
  60.    Operator("\\Huge",            0,0,Environment::PFont,        Font::Huge,                0.0,  "",                  Stack::set),                 // handled
  61.    Operator("\\LARGE",           0,0,Environment::PFont,        Font::LARGE,               0.0,  "",                  Stack::set),                 // handled
  62.    Operator("\\Large",           0,0,Environment::PFont,        Font::Large,               0.0,  "",                  Stack::set),                 // handled
  63.    Operator("\\STEALTH",         0,0,Environment::PDocument,    Document::Stealth,         2.0,  "",                  Stack::set),                 // handled
  64.    Operator("\\\\",              1,0,Environment::PDocument,    Document::NewLine,         0.0,  "",                  Stack::set),                 // handled
  65.    Operator("\\\\*",             1,0,Environment::PDocument,    Document::NewLine,         0.0,  "",                  Stack::set),                 // handled
  66.    Operator("\\_",               1,0,Environment::PFont,        Font::FunnyPrint,          0.0,  "(_)",               Stack::set),                 // handled
  67.    Operator("\\addtolength",     0,0,0,                         0,                         0.0,  "",                  Operator::addtolength),      // handled
  68.    Operator("\\backslash",       1,0,Environment::PFont,        Font::FunnyPrint,          0.0,  "(\\\\)",            Stack::set),                 // handled
  69.    Operator("\\begin",           0,0,0,                         0,                         0.0,  "",                  Document::begin),            // handled
  70.    Operator("\\bf",              0,0,Environment::PFont,        Font::Bold,                0.0,  "",                  Stack::set),                 // handled
  71.    Operator("\\bigskip",         1,0,0,                         0,                         0.0,  "\\bigskipamount",   Operator::do_vspace), 
  72.    Operator("\\center",          0,0,Environment::PJustify,     Justify::Center,           0.0,  "",                  Stack::set),                 // handled
  73.    Operator("\\chapter",         0,0,0,                         0,                         0.0,  "",                  Operator::clearpage),        // handled
  74.    Operator("\\chapter",         1,0,Environment::PDocument,    Document::JustDidSection,  1.0,  "",                  Stack::set),                 // handled
  75.    Operator("\\chapter",         1,0,0,                         0,                         0.0,  "",                  Stack::push),                // handled
  76.    Operator("\\chapter",         1,0,Environment::PLength,      Length::Parameter,         0.0,  "\\parindent",       Stack::set),                 // handled
  77.    Operator("\\chapter",         1,0,Environment::PFont,        Font::Bold,                0.0,  "",                  Stack::set),                 // handled
  78.    Operator("\\chapter",         1,0,Environment::PFont,        Font::huge,                0.0,  "",                  Stack::set),                 // handled
  79.    Operator("\\chapter",         1,0,Environment::PCounter,     Counter::Chapter,          1.0,  "",                  Stack::set),                 // handled
  80.    Operator("\\chapter*",        0,0,0,                         0,                         0.0,  "",                  Operator::clearpage),        // handled
  81.    Operator("\\chapter*",        1,0,Environment::PDocument,    Document::JustDidSection,  1.0,  "",                  Stack::set),                 // handled
  82.    Operator("\\chapter*",        1,0,0,                         0,                         0.0,  "",                  Stack::push),                // handled
  83.    Operator("\\chapter*",        1,0,Environment::PLength,      Length::Parameter,         0.0,  "\\parindent",       Stack::set),                 // handled
  84.    Operator("\\chapter*",        1,0,Environment::PFont,        Font::Bold,                0.0,  "",                  Stack::set),                 // handled
  85.    Operator("\\chapter*",        1,0,Environment::PFont,        Font::huge,                0.0,  "",                  Stack::set),                 // handled
  86.    Operator("\\chapter*",        1,0,Environment::PCounter,     Counter::Chapter,          0.0,  "",                  Stack::set),                 // handled
  87.    Operator("\\clearpage",       0,0,0,                         0,                         0.0,  "",                  Operator::clearpage),        // handled
  88.    Operator("\\description",     1,0,Environment::PCounter,     Counter::Description,      0.0,  "",                  Stack::set),                 // handled
  89.    Operator("\\description",     1,0,Environment::PLength,      Length::Parameter,        22.5,  "\\oddsidemargin",   Stack::relative_set),        // handled
  90.    Operator("\\description",     1,0,Environment::PLength,      Length::Parameter,       -22.5,  "\\textwidth",       Stack::relative_set),        // handled
  91.    Operator("\\description",     1,0,Environment::PLength,      Length::Parameter,         0.0,  "\\parindent",       Stack::set),                 // handled
  92.    Operator("\\description",     1,0,Environment::PLength,      Length::Parameter,         1.14, "\\baselinestretch", Stack::set),                 // handled
  93.    Operator("\\document",        0,0,Environment::PDocument,    Document::DocumentStart,   1.0,  "",                  Stack::set),                 // handled
  94.    Operator("\\documentstyle",   0,0,0,                         0,                         0.0,  "",                  Document::documentstyle),    // handled
  95.    Operator("\\em",              0,0,Environment::PFont,        Font::Italic,              0.0,  "",                  Stack::set),                 // handled
  96.    Operator("\\end",             0,0,0,                         0,                         0.0,  "",                  Document::end),              // handled
  97.    Operator("\\enumerate",       1,0,Environment::PCounter,     Counter::Enum,             0.0,  "",                  Stack::set),                 // handled
  98.    Operator("\\enumerate",       1,0,Environment::PLength,      Length::Parameter,        22.5,  "\\oddsidemargin",   Stack::relative_set),        // handled
  99.    Operator("\\enumerate",       1,0,Environment::PLength,      Length::Parameter,       -22.5,  "\\textwidth",       Stack::relative_set),        // handled
  100.    Operator("\\enumerate",       1,0,Environment::PLength,      Length::Parameter,         1.14, "\\baselinestretch", Stack::set),                 // handled
  101.    Operator("\\enumerate",       1,0,Environment::PLength,      Length::Parameter,         0.0,  "\\parindent",       Stack::set),                 // handled
  102.    Operator("\\flushleft",       0,0,Environment::PJustify,     Justify::FlushLeft,        0.0,  "",                  Stack::set),                 // handled
  103.    Operator("\\flushright",      0,0,Environment::PJustify,     Justify::FlushRight,       0.0,  "",                  Stack::set),                 // handled
  104.    Operator("\\footnotesize",    0,0,Environment::PFont,        Font::Footnotesize,        0.0,  "",                  Stack::set),                 // handled
  105.    Operator("\\hspace",          1,0,0,                         0,                         0.0,  "",                  Operator::hspace),           // handled
  106.    Operator("\\hspace*",         1,0,0,                         0,                         0.0,  "",                  Operator::hspace),           // handled
  107.    Operator("\\huge",            0,0,Environment::PFont,        Font::huge,                0.0,  "",                  Stack::set),                 // handled
  108.    Operator("\\hyphenation",     0,0,0,                         0,                         0.0,  "",                  Operator::skip),             // skipped
  109.    Operator("\\ignore",          1,1,Environment::PDocument,    Document::Ignore,          1.0,  "",                  Stack::set),                 // handled
  110.    Operator("\\include",         0,0,0,                         0,                         0.0,  "",                  Operator::include_file),     // handled
  111.    Operator("\\includeps",       0,1,0,                         0,                         0.0,  "",                  Operator::includeps),        // handled
  112.    Operator("\\input",           0,0,0,                         0,                         0.0,  "",                  Operator::include_file),     // handled
  113.    Operator("\\it",              0,0,Environment::PFont,        Font::Italic,              0.0,  "",                  Stack::set),                 // handled
  114.    Operator("\\item",            1,0,Environment::PCounter,     Counter::Item,             0.0,  "",                  Stack::set),                 // handled
  115.    Operator("\\itemize",         1,0,Environment::PCounter,     Counter::Itemize,          0.0,  "",                  Stack::set),                 // handled
  116.    Operator("\\itemize",         1,0,Environment::PLength,      Length::Parameter,        22.5,  "\\oddsidemargin",   Stack::relative_set),        // handled
  117.    Operator("\\itemize",         1,0,Environment::PLength,      Length::Parameter,       -22.5,  "\\textwidth",       Stack::relative_set),        // handled
  118.    Operator("\\itemize",         1,0,Environment::PLength,      Length::Parameter,         1.0,  "\\baselinestretch", Stack::set),                 // handled
  119.    Operator("\\itemize",         1,0,Environment::PLength,      Length::Parameter,         0.0,  "\\parindent",       Stack::set),                 // handled
  120.    Operator("\\label",           1,0,0,                         0,                         0.0,  "",                  Operator::label),            // handled
  121.    Operator("\\large",           0,0,Environment::PFont,        Font::large,               0.0,  "",                  Stack::set),                 // handled
  122.    Operator("\\ldots",           1,0,0,                         0,                         0.0,  "...",               Operator::replace),          // handled
  123.    Operator("\\medskip",         1,0,0,                         0,                         0.0,  "\\medskipamount",   Operator::do_vspace),
  124.    Operator("\\newlength",       0,0,0,                         0,                         0.0,  "",                  Operator::newlength),        // handled
  125.    Operator("\\newline",         1,0,Environment::PDocument,    Document::NewLine,         0.0,  "",                  Stack::set),                 // handled
  126.    Operator("\\normalsize",      0,0,Environment::PFont,        Font::Normalsize,          0.0,  "",                  Stack::set),                 // handled
  127.    Operator("\\par",             1,0,Environment::PDocument,    Document::NewLine,         0.0,  "",                  Stack::set),                 // handled
  128.    Operator("\\paragraph",       1,0,Environment::PDocument,    Document::JustDidSection,  1.0,  "",                  Stack::set),
  129.    Operator("\\paragraph",       1,0,0,                         0,                         0.0,  "",                  Stack::push),                // handled
  130.    Operator("\\paragraph",       1,0,Environment::PLength,      Length::Parameter,         0.0,  "\\parindent",       Stack::set),                 // handled
  131.    Operator("\\paragraph",       1,0,Environment::PFont,        Font::Bold,                0.0,  "",                  Stack::set),                 // handled
  132.    Operator("\\paragraph",       1,0,Environment::PFont,        Font::Normalsize,          0.0,  "",                  Stack::set),                 // handled
  133.    Operator("\\paragraph",       1,0,Environment::PCounter,     Counter::Paragraph,        1.0,  "",                  Stack::set),                 // handled
  134.    Operator("\\paragraph*",      1,0,Environment::PDocument,    Document::JustDidSection,  1.0,  "",                  Stack::set),
  135.    Operator("\\paragraph*",      1,0,0,                         0,                         0.0,  "",                  Stack::push),                // handled
  136.    Operator("\\paragraph*",      1,0,Environment::PLength,      Length::Parameter,         0.0,  "\\parindent",       Stack::set),                 // handled
  137.    Operator("\\paragraph*",      1,0,Environment::PFont,        Font::Bold,                0.0,  "",                  Stack::set),                 // handled
  138.    Operator("\\paragraph*",      1,0,Environment::PFont,        Font::Normalsize,          0.0,  "",                  Stack::set),                 // handled
  139.    Operator("\\paragraph*",      1,0,Environment::PCounter,     Counter::Paragraph,        0.0,  "",                  Stack::set),                 // handled
  140.    Operator("\\part",            0,0,0,                         0,                         0.0,  "",                  Operator::clearpage),
  141.    Operator("\\part",            1,0,Environment::PDocument,    Document::JustDidSection,  1.0,  "",                  Stack::set),
  142.    Operator("\\part",            1,0,0,                         0,                         0.0,  "",                  Stack::push),
  143.    Operator("\\part",            1,0,Environment::PLength,      Length::Parameter,         0.0,  "\\parindent",       Stack::set),
  144.    Operator("\\part",            1,0,Environment::PFont,        Font::Bold,                0.0,  "",                  Stack::set),
  145.    Operator("\\part",            1,0,Environment::PFont,        Font::Huge,                0.0,  "",                  Stack::set),
  146.    Operator("\\part",            1,0,Environment::PCounter,     Counter::Part,             1.0,  "",                  Stack::set),
  147.    Operator("\\part*",           0,0,0,                         0,                         0.0,  "",                  Operator::clearpage),
  148.    Operator("\\part*",           1,0,Environment::PDocument,    Document::JustDidSection,  1.0,  "",                  Stack::set),
  149.    Operator("\\part*",           1,0,0,                         0,                         0.0,  "",                  Stack::push),
  150.    Operator("\\part*",           1,0,Environment::PLength,      Length::Parameter,         0.0,  "\\parindent",       Stack::set),
  151.    Operator("\\part*",           1,0,Environment::PFont,        Font::Bold,                0.0,  "",                  Stack::set),
  152.    Operator("\\part*",           1,0,Environment::PFont,        Font::Huge,                0.0,  "",                  Stack::set),
  153.    Operator("\\part*",           1,0,Environment::PCounter,     Counter::Part,             0.0,  "",                  Stack::set),
  154.    Operator("\\postscript",      1,1,Environment::PDocument,    Document::PostScript,      1.0,  "",                  Stack::set),                 // handled
  155.    Operator("\\pscmd",           0,1,0,                         0,                         0.0,  "",                  Operator::pscmd),            // handled
  156.    Operator("\\pspage",          0,1,0,                         0,                         0.0,  "",                  Operator::pspage),           // handled
  157.    Operator("\\quotation",       1,0,Environment::PDocument,    Document::NewLine,         0.0,  "",                  Stack::set),                 // handled
  158.    Operator("\\quotation",       1,0,Environment::PLength,      Length::Parameter,         0.0,  "\\parindent",       Stack::set),                 // handled
  159.    Operator("\\quotation",       1,0,Environment::PLength,      Length::Parameter,         1.0,  "\\baselinestretch", Stack::set),                 // handled
  160.    Operator("\\quotation",       1,0,Environment::PLength,      Length::Parameter,         0.0,  "\\parskip",         Stack::set),                 // handled
  161.    Operator("\\quotation",       1,0,Environment::PLength,      Length::Parameter,        72.0,  "\\oddsidemargin",   Stack::relative_set),        // handled
  162.    Operator("\\quotation",       1,0,Environment::PLength,      Length::Parameter,       -72.0,  "\\textwidth",       Stack::relative_set),        // handled
  163.    Operator("\\quote",           1,0,Environment::PDocument,    Document::NewLine,         0.0,  "",                  Stack::set),                 // handled
  164.    Operator("\\quote",           1,0,Environment::PLength,      Length::Parameter,         0.0,  "\\parindent",       Stack::set),                 // handled
  165.    Operator("\\quote",           1,0,Environment::PLength,      Length::Parameter,         1.0,  "\\baselinestretch", Stack::set),                 // handled
  166.    Operator("\\quote",           1,0,Environment::PLength,      Length::Parameter,         0.0,  "\\parskip",         Stack::set),                 // handled
  167.    Operator("\\quote",           1,0,Environment::PLength,      Length::Parameter,        72.0,  "\\oddsidemargin",   Stack::relative_set),        // handled
  168.    Operator("\\quote",           1,0,Environment::PLength,      Length::Parameter,       -72.0,  "\\textwidth",       Stack::relative_set),        // handled
  169.    Operator("\\raggedleft",      0,0,Environment::PJustify,     Justify::FlushRight,       0.0,  "",                  Stack::set),                 // handled
  170.    Operator("\\raggedright",     0,0,Environment::PJustify,     Justify::FlushLeft,        0.0,  "",                  Stack::set),                 // handled
  171.    Operator("\\ref",             1,0,0,                         0,                         0.0,  "",                  Operator::ref),              // handled
  172.    Operator("\\rm",              0,0,Environment::PFont,        Font::Roman,               0.0,  "",                  Stack::set),                 // handled
  173.    Operator("\\sc",              0,0,Environment::PFont,        Font::SmallCaps,           0.0,  "",                  Stack::set),                 // handled
  174.    Operator("\\scriptsize",      0,0,Environment::PFont,        Font::Scriptsize,          0.0,  "",                  Stack::set),                 // handled
  175.    Operator("\\section",         1,0,Environment::PDocument,    Document::JustDidSection,  1.0,  "",                  Stack::set),                 // handled
  176.    Operator("\\section",         1,0,0,                         0,                         0.0,  "",                  Stack::push),                // handled
  177.    Operator("\\section",         1,0,Environment::PLength,      Length::Parameter,         0.0,  "\\parindent",       Stack::set),                 // handled
  178.    Operator("\\section",         1,0,Environment::PFont,        Font::Bold,                0.0,  "",                  Stack::set),                 // handled
  179.    Operator("\\section",         1,0,Environment::PFont,        Font::Large,               0.0,  "",                  Stack::set),                 // handled
  180.    Operator("\\section",         1,0,Environment::PCounter,     Counter::Section,          1.0,  "",                  Stack::set),                 // handled
  181.    Operator("\\section*",        1,0,Environment::PDocument,    Document::JustDidSection,  1.0,  "",                  Stack::set),                 // handled
  182.    Operator("\\section*",        1,0,0,                         0,                         0.0,  "",                  Stack::push),                // handled
  183.    Operator("\\section*",        1,0,Environment::PLength,      Length::Parameter,         0.0,  "\\parindent",       Stack::set),                 // handled
  184.    Operator("\\section*",        1,0,Environment::PFont,        Font::Bold,                0.0,  "",                  Stack::set),                 // handled
  185.    Operator("\\section*",        1,0,Environment::PFont,        Font::Large,               0.0,  "",                  Stack::set),                 // handled
  186.    Operator("\\section*",        1,0,Environment::PCounter,     Counter::Section,          0.0,  "",                  Stack::set),                 // handled
  187.    Operator("\\setlength",       0,0,0,                         0,                         0.0,  "",                  Operator::setlength),        // handled
  188.    Operator("\\sf",              0,0,Environment::PFont,        Font::SansSerif,           0.0,  "",                  Stack::set),                 // handled
  189.    Operator("\\sl",              0,0,Environment::PFont,        Font::Slant,               0.0,  "",                  Stack::set),                 // handled
  190.    Operator("\\small",           0,0,Environment::PFont,        Font::Small,               0.0,  "",                  Stack::set),                 // handled
  191.    Operator("\\smallskip",       1,0,0,                         0,                         0.0,  "\\smallskipamount", Operator::do_vspace),
  192.    Operator("\\stealth",         0,0,Environment::PDocument,    Document::Stealth,         1.0,  "",                  Stack::set),                 // handled
  193.    Operator("\\subparagraph",    1,0,Environment::PDocument,    Document::JustDidSection,  1.0,  "",                  Stack::set),                 // handled
  194.    Operator("\\subparagraph",    1,0,0,                         0,                         0.0,  "",                  Stack::push),                // handled
  195.    Operator("\\subparagraph",    1,0,Environment::PLength,      Length::Parameter,         0.0,  "\\parindent",       Stack::set),                 // handled
  196.    Operator("\\subparagraph",    1,0,Environment::PFont,        Font::Bold,                0.0,  "",                  Stack::set),                 // handled
  197.    Operator("\\subparagraph",    1,0,Environment::PFont,        Font::Normalsize,          0.0,  "",                  Stack::set),                 // handled
  198.    Operator("\\subparagraph",    1,0,Environment::PCounter,     Counter::Subparagraph,     1.0,  "",                  Stack::set),                 // handled
  199.    Operator("\\subparagraph*",   1,0,Environment::PDocument,    Document::JustDidSection,  1.0,  "",                  Stack::set),                 // handled
  200.    Operator("\\subparagraph*",   1,0,0,                         0,                         0.0,  "",                  Stack::push),                // handled
  201.    Operator("\\subparagraph*",   1,0,Environment::PLength,      Length::Parameter,         0.0,  "\\parindent",       Stack::set),                 // handled
  202.    Operator("\\subparagraph*",   1,0,Environment::PFont,        Font::Bold,                0.0,  "",                  Stack::set),                 // handled
  203.    Operator("\\subparagraph*",   1,0,Environment::PFont,        Font::Normalsize,          0.0,  "",                  Stack::set),                 // handled
  204.    Operator("\\subparagraph*",   1,0,Environment::PCounter,     Counter::Subparagraph,     0.0,  "",                  Stack::set),                 // handled
  205.    Operator("\\subsection",      1,0,Environment::PDocument,    Document::JustDidSection,  1.0,  "",                  Stack::set),                 // handled
  206.    Operator("\\subsection",      1,0,0,                         0,                         0.0,  "",                  Stack::push),                // handled
  207.    Operator("\\subsection",      1,0,Environment::PLength,      Length::Parameter,         0.0,  "\\parindent",       Stack::set),                 // handled
  208.    Operator("\\subsection",      1,0,Environment::PFont,        Font::Bold,                0.0,  "",                  Stack::set),                 // handled
  209.    Operator("\\subsection",      1,0,Environment::PFont,        Font::large,               0.0,  "",                  Stack::set),                 // handled
  210.    Operator("\\subsection",      1,0,Environment::PCounter,     Counter::Subsection,       1.0,  "",                  Stack::set),                 // handled
  211.    Operator("\\subsection*",     1,0,Environment::PDocument,    Document::JustDidSection,  1.0,  "",                  Stack::set),                 // handled
  212.    Operator("\\subsection*",     1,0,0,                         0,                         0.0,  "",                  Stack::push),                // handled
  213.    Operator("\\subsection*",     1,0,Environment::PLength,      Length::Parameter,         0.0,  "\\parindent",       Stack::set),                 // handled
  214.    Operator("\\subsection*",     1,0,Environment::PFont,        Font::Bold,                0.0,  "",                  Stack::set),                 // handled
  215.    Operator("\\subsection*",     1,0,Environment::PFont,        Font::large,               0.0,  "",                  Stack::set),                 // handled
  216.    Operator("\\subsection*",     1,0,Environment::PCounter,     Counter::Subsection,       0.0,  "",                  Stack::set),                 // handled
  217.    Operator("\\subsubsection",   1,0,Environment::PDocument,    Document::JustDidSection,  1.0,  "",                  Stack::set),                 // handled
  218.    Operator("\\subsubsection",   1,0,0,                         0,                         0.0,  "",                  Stack::push),                // handled
  219.    Operator("\\subsubsection",   1,0,Environment::PLength,      Length::Parameter,         0.0,  "\\parindent",       Stack::set),                 // handled
  220.    Operator("\\subsubsection",   1,0,Environment::PFont,        Font::Bold,                0.0,  "",                  Stack::set),                 // handled
  221.    Operator("\\subsubsection",   1,0,Environment::PFont,        Font::Normalsize,          0.0,  "",                  Stack::set),                 // handled
  222.    Operator("\\subsubsection",   1,0,Environment::PCounter,     Counter::Subsubsection,    1.0,  "",                  Stack::set),                 // handled
  223.    Operator("\\subsubsection*",  1,0,Environment::PDocument,    Document::JustDidSection,  1.0,  "",                  Stack::set),                 // handled
  224.    Operator("\\subsubsection*",  1,0,0,                         0,                         0.0,  "",                  Stack::push),                // handled
  225.    Operator("\\subsubsection*",  1,0,Environment::PLength,      Length::Parameter,         0.0,  "\\parindent",       Stack::set),                 // handled
  226.    Operator("\\subsubsection*",  1,0,Environment::PFont,        Font::Bold,                0.0,  "",                  Stack::set),                 // handled
  227.    Operator("\\subsubsection*",  1,0,Environment::PFont,        Font::Normalsize,          0.0,  "",                  Stack::set),                 // handled
  228.    Operator("\\subsubsection*",  1,0,Environment::PCounter,     Counter::Subsubsection,    0.0,  "",                  Stack::set),                 // handled
  229.    Operator("\\tiny",            0,0,Environment::PFont,        Font::Tiny,                0.0,  "",                  Stack::set),                 // handled
  230.    Operator("\\today",           1,0,0,                         0,                         0.0,  "",                  Operator::today),            // handled
  231.    Operator("\\tt",              0,0,Environment::PFont,        Font::Typewriter,          0.0,  "",                  Stack::set),                 // handled
  232.    Operator("\\verbatim",        1,0,Environment::PFont,        Font::Typewriter,          0.0,  "",                  Stack::set),                 // handled
  233.    Operator("\\verbatim",        1,0,Environment::PJustify,     Justify::FlushLeft,        0.0,  "",                  Stack::set),                 // handled
  234.    Operator("\\verbatim",        1,0,Environment::PLength,      Length::Parameter,         0.0,  "\\parindent",       Stack::set),                 // handled
  235.    Operator("\\verbatim",        1,0,Environment::PLength,      Length::Parameter,         1.0,  "\\baselinestretch", Stack::set),                 // handled
  236.    Operator("\\verbatim",        1,0,Environment::PLength,      Length::Parameter,         0.0,  "\\parskip",         Stack::set),                 // handled
  237.    Operator("\\verbatim",        1,0,Environment::PDocument,    Document::Verbatim,        1.0,  "",                  Stack::set),                 // handled
  238.    Operator("\\verbatim*",       1,0,Environment::PFont,        Font::Typewriter,          0.0,  "",                  Stack::set),                 // handled
  239.    Operator("\\verbatim*",       1,0,Environment::PJustify,     Justify::FlushLeft,        0.0,  "",                  Stack::set),                 // handled
  240.    Operator("\\verbatim*",       1,0,Environment::PLength,      Length::Parameter,         0.0,  "\\parindent",       Stack::set),                 // handled
  241.    Operator("\\verbatim*",       1,0,Environment::PLength,      Length::Parameter,         1.0,  "\\baselinestretch", Stack::set),                 // handled
  242.    Operator("\\verbatim*",       1,0,Environment::PLength,      Length::Parameter,         0.0,  "\\parskip",         Stack::set),                 // handled
  243.    Operator("\\verbatim*",       1,0,Environment::PDocument,    Document::Verbatim,        1.0,  "",                  Stack::set),                 // handled
  244.    Operator("\\verse",           1,0,Environment::PDocument,    Document::NewLine,         0.0,  "",                  Stack::set),                 // handled
  245.    Operator("\\verse",           1,0,Environment::PLength,      Length::Parameter,        45.0,  "\\oddsidemargin",   Stack::relative_set),        // handled
  246.    Operator("\\verse",           1,0,Environment::PLength,      Length::Parameter,       -22.5,  "\\parindent",       Stack::set),                 // handled
  247.    Operator("\\verse",           1,0,Environment::PLength,      Length::Parameter,         1.0,  "\\baselinestretch", Stack::set),                 // handled
  248.    Operator("\\verse",           1,0,Environment::PLength,      Length::Parameter,        11.0,  "\\parskip",         Stack::set),                 // handled
  249.    Operator("\\vspace",          1,0,0,                         0,                         0.0,  "",                  Operator::vspace),           // handled
  250.    Operator("\\vspace*",         1,0,0,                         0,                         0.0,  "",                  Operator::vspace),           // handled
  251.    Operator("\\{",               1,0,Environment::PFont,        Font::FunnyPrint,          0.0,  "({)",               Stack::set),                 // handled
  252.    Operator("\\}",               1,0,Environment::PFont,        Font::FunnyPrint,          0.0,  "(})",               Stack::set),                 // handled
  253.    Operator("{",                 0,0,0,                         0,                         0.0,  "",                  Stack::push),                // handled
  254.    Operator("}",                 0,0,0,                         Document::CloseBrace,      0.0,  "",                  Stack::pop),                 // handled
  255.    0
  256. };
  257.  
  258. static int operator_size = 0; // Size of the operators array
  259.  
  260. int Operator::compare(const void *op1, const void *op2)
  261. {
  262.    Operator *oper1;
  263.    Operator *oper2;
  264.    oper1 = (Operator *) op1;
  265.    oper2 = (Operator *) op2;
  266.    return strcmp(oper1->_tokentext, oper2->_tokentext);
  267. }
  268.  
  269. /* Do a binary search through the alphabetically sorted array of operators
  270.  * for the first operator (there may be many) that matches this token name
  271.  * Return a pointer to the first operator, or NULL if no match found.
  272.  */
  273. Operator* Operator::get_operator(char *tokenstr)
  274. {
  275.    if(!operator_size)       // Has the operator_size variable been initialized?
  276.       while(operators[operator_size++].isvalid())
  277.      ;
  278.    Operator key(tokenstr, 0, 0, 0, 0, 0.0, "", NULL);
  279.    Operator *op = (Operator *)
  280.       bsearch((char *)&key, (char *) operators,
  281.           operator_size, sizeof(Operator), Operator::compare);
  282.    if(op != NULL && !op->match("")) {    // Found a non-null match?
  283.       while((--op)->match(tokenstr))     // Backpeddle until first match found.
  284.      ;
  285.       op++;
  286.    }
  287.    return op;
  288. }
  289.  
  290. /* Execute the given operator, which is a pointer into the array of operators
  291.  * "operators". Since there could be more than one operator for a token name,
  292.  * the pointer is incremented and executed until the token name doesn't match.
  293.  */
  294. void Operator::execute()
  295. {
  296.    // Skip the operation if we're in a comment, unless this is a 
  297.    // stealth environment or the command is "\stealth" or "\begin".
  298.  
  299.    if(Stack::get(Environment::PDocument, Document::Comment, "")) { // Comment?
  300.       if(!match("\\stealth") && !match("\\STEALTH") && !match("\\begin")
  301.      && !Stack::get(Environment::PDocument, Document::Stealth, ""))
  302.      return;
  303.    }
  304.    else              // Don't put stealth comments outside of a comment line,
  305.       if(is_stealth()) // because then normal LaTeX cannot process this file.
  306.      Global::files->fatal_error(
  307.  "Cannot execute stealth command outside of stealth environment in comment line.");
  308.  
  309.    // We are prepared to handle the Operator. But first, check to see if the
  310.    // page description needs to be defined or if the current page needs to be
  311.    // started with StartPage
  312.    if(_page_specific)
  313.       Global::files->force_start_page();
  314.  
  315.    _handle(_paramtype, _subtype, _value, _replacestr); // Execute the operator
  316. }
  317.  
  318. /* Returns true if the given token string matches the Operator's token string
  319.  */
  320. int Operator::match(char *tokenstr)
  321. {
  322.    return !strcmp(_tokentext,tokenstr);
  323. }
  324.  
  325. void Operator::addtolength(int paramtype, int subtype, float value,
  326.                          char *replacestr)
  327. {
  328.    Length *length;
  329.    length = Global::stack->get_length();
  330.    length->addtolength(paramtype, subtype, value, replacestr);
  331. }
  332.  
  333. void Operator::clearpage(int, int, float, char *)
  334. {
  335.    if(Stack::get(Environment::PDocument, Document::StartPage, "")) {
  336.       Global::files->outfile << endl;
  337.       Global::files->outfile << "ENDPAGE" << endl;
  338.       // We don't start a new page unless we have to! This is just a marker
  339.       // that a new page has not been started.
  340.       Stack::set(Environment::PDocument, Document::StartPage, 0.0, "");
  341.    }
  342. }
  343.  
  344. void Operator::document(int, int, float, char *)
  345. {
  346.    Global::files->outfile << "in document()" << endl;
  347. }
  348.  
  349. void Operator::do_vspace(int, int, float height, char *length_param)
  350. {
  351.    if(length_param[0])
  352.       height = Global::stack->get(Environment::PLength,
  353.                   Length::Parameter, length_param);
  354.  
  355.    // Suppress any new paragraphs before text
  356.    Global::files->blankline_area = 1; 
  357.    Global::files->newline_in_this_blankline_area = 1; 
  358.    Global::files->vspace_in_this_blankline_area += height; 
  359.    Global::files->got_whitespace();
  360. }
  361.  
  362. void Operator::hspace(int, int, float, char *)
  363. {
  364.    Token openbrace;
  365.    if(!openbrace.match("{"))
  366.       Global::files->fatal_error("Expecting '{' after \\vspace");
  367.    
  368.    float width = Stack::get(Environment::PLength, Length::Parse_Length, "");
  369.    Global::files->outfile << endl;
  370.    Global::files->outfile << width << " HSpace" << endl;
  371. }
  372.  
  373. /* Handle the LaTeX command \include, which includes a file at the current
  374.  * place in the filestream.
  375.  */
  376. void Operator::include_file(int, int, float, char *)
  377. {
  378.    Token openbrace;
  379.    if(!openbrace.match("{"))
  380.       Global::files->fatal_error("Expecting '{' after \\include statement");
  381.    
  382.    Token filename;
  383.    if(filename.match("}"))
  384.       Global::files->warning(
  385.             "Expecting filename before closing '}' in \\include");
  386.  
  387.    Token closebrace;
  388.    if(!closebrace.match("}"))
  389.       Global::files->fatal_error(
  390.          "More than one word before closing '}' in \\include");
  391.  
  392.    Global::files->include_file(filename.get_text());
  393. }
  394.  
  395. /* Handle the LameTeX stealth command \includeps, which includes a
  396.  * postscript file at the current place in the filestream.
  397.  */
  398. void Operator::includeps(int, int, float, char *)
  399. {
  400.    Token openbrace;
  401.    if(!openbrace.match("{"))
  402.       Global::files->fatal_error("Expecting '{' after \\includeps statement");
  403.    
  404.    Token filename;
  405.    if(filename.match("}"))
  406.       Global::files->warning(
  407.             "Expecting filename before closing '}' in \\includeps");
  408.  
  409.    Token closebrace;
  410.    if(!closebrace.match("}"))
  411.       Global::files->fatal_error(
  412.          "More than one word before closing '}' in \\includeps");
  413.  
  414.    Global::files->include_file_ps(filename.get_text(), FALSE);
  415. }
  416.  
  417.  
  418. void Operator::label(int, int, float, char *)
  419. {
  420.    Token openbrace;
  421.    if(!openbrace.match("{"))
  422.       Global::files->fatal_error("Expecting '{' after \\label statement");
  423.    
  424.    Token labelname;
  425.    if(labelname.match("}"))
  426.       Global::files->warning(
  427.             "Expecting label name before closing '}' in \\label");
  428.  
  429.    Token closebrace;
  430.    if(!closebrace.match("}"))
  431.       Global::files->fatal_error(
  432.          "More than token before closing '}' in \\label. Sorry, you must rename your label.");
  433.  
  434.    Global::labels->add_label(labelname.get_text());
  435. }
  436.  
  437. void Operator::newlength(int paramtype, int subtype, float value,
  438.                          char *replacestr)
  439. {
  440.    Length *length;
  441.    length = Global::stack->get_length();
  442.    length->newlength(paramtype, subtype, value, replacestr);
  443. }
  444.  
  445. void Operator::new_paragraph(int, int, float, char *)
  446. {
  447.    if(Global::files->blankline_area)
  448.       return;
  449.  
  450.    // Suppress more new paragraphs.
  451.    Global::files->newline_in_this_blankline_area = 1; 
  452. }
  453.  
  454. /* LaTeX Fonts are bulky, and in LameTeX (just like LaTeX) the fonts
  455.  * are included one character at a time, not one fontfamily at a time.
  456.  * A fontfamily is much too large to load in if we're only going to
  457.  * use a couple of characters from the font type.
  458.  *
  459.  * So, whenever we send to PostScript a character meant to be part of a string
  460.  * we should register that the font description for this character in the
  461.  * current font type should be included.
  462.  *
  463.  * This routine performs this registration. Also it adds the syntax
  464.  * necessary for PostScript to print this string, returning it in textout.
  465.  */
  466. void Operator::registrar(char *textin, char *textout)
  467. {
  468.    Stack::set(Environment::PFont, Font::Used, 0.0, textin);
  469.  
  470.    int linelength=0;
  471.    textout[0]='(';
  472.    for(int in=0,out=1; textin[in]; in++,out++) {
  473.       if(iscntrl(textin[in]) && textin[in]!='\t')
  474.        textout[out]=' ';
  475.       else
  476.        switch(textin[in]) {
  477.          case '\n':
  478.         textout[out++]='\\';
  479.         textout[out]='n';
  480.         break;
  481.          case '\t':
  482.         if(Global::files->plain_text_output) {
  483.              do {
  484.               linelength++;
  485.               textout[out++]='\\';
  486.               textout[out++]='_';
  487.              } while(linelength%8 !=0);
  488.                      out--;
  489.         } else {
  490.              textout[out++]='\\';
  491.              textout[out]='t';
  492.         }
  493.         break;
  494.          case '\r':
  495.         textout[out++]='\\';
  496.         textout[out]='r';
  497.         break;
  498.          case '^':
  499.          case '}':
  500.          case '{':
  501.         if(Global::files->plain_text_output) {
  502.              linelength++;
  503.              textout[out]=textin[in];
  504.         }
  505.         break;
  506.          case '`':
  507.                 if(Global::files->plain_text_output) {
  508.              linelength++;
  509.              textout[out]=textin[in];
  510.         }
  511.         else {
  512.              if(textin[in+1]=='`') {
  513.               in++;
  514.               textout[out++]='\\';
  515.               textout[out]='\\';
  516.              }
  517.              else
  518.               textout[out]='`';
  519.         }
  520.         break;
  521.          case '\'':
  522.                 if(Global::files->plain_text_output) {
  523.              linelength++;
  524.              textout[out]=textin[in];
  525.         }
  526.         else {
  527.              if(textin[in+1]=='\'') {
  528.               in++;
  529.               textout[out]='\"';
  530.              }
  531.              else
  532.               textout[out]='\'';
  533.         }
  534.         break;
  535.          case ' ':
  536.                 if(Global::files->plain_text_output) {
  537.              linelength++;
  538.              textout[out++]='\\';
  539.              textout[out]='_';
  540.         }
  541.         else
  542.              textout[out]=textin[in];
  543.         break;
  544.          case '\\':
  545.          case ')':
  546.          case '(':
  547.                 if(!Global::files->plain_text_output)
  548.              textout[out++]='\\';
  549.          default:
  550.         linelength++;
  551.         textout[out]=textin[in];
  552.        }
  553.    }
  554.    textout[out++]=')';
  555.    textout[out]='\0';
  556. }
  557.  
  558. /* If we are inside the middle of the document, then print this plaintext
  559.  * normally.
  560.  */
  561. void Operator::plaintext(char *text)
  562. {
  563.    // Plaintext is not valid in a comment that's not in a stealth environment.
  564.    if(Stack::get(Environment::PDocument, Document::Comment, "")
  565.       && !Stack::get(Environment::PDocument, Document::Stealth, ""))
  566.       return;
  567.  
  568.    if(!Stack::get(Environment::PDocument,Document::DocumentStart,"")) {
  569.       Global::files->warning("Missing \\begin{document}.");
  570.       return;
  571.    }
  572.  
  573.    Global::files->force_start_page();  // Start a new page if not started.
  574.  
  575.    // This is NOT just after a new section.
  576.    Global::stack->set(Environment::PDocument,
  577.               Document::JustDidSection, 0.0, "");
  578.  
  579.    if(Global::files->readjust_vspace > 0.0) {
  580.       Global::files->outfile << endl
  581.      << Global::files->readjust_vspace
  582.      << " woids 1 gt { 0 exch READJUST } { pop } ifelse" << endl;
  583.       Global::files->readjust_vspace = 0.0;
  584.    }
  585.  
  586.    // Must process for special characters!
  587.    char output[MAXSTRING];
  588.    Operator::registrar(text, output);
  589.    Global::files->outfile << " " << output << " NW";
  590. }
  591.  
  592. /* Shleps a PostScript operator into the word list */
  593. void Operator::pscmd(int, int, float, char *)
  594. {
  595.    char commandline[MAXSTRING+5];
  596.    char buildline[MAXSTRING];
  597.  
  598.    Token openbrace;
  599.    if(!openbrace.match("{"))
  600.       Global::files->fatal_error("Expecting '{' after \\pscmd statement");
  601.    
  602.    strcpy(buildline,"");
  603.  
  604.    int x=0;
  605.    for(Token command; !command.match("}"); command = Token()) {
  606.       if(x++>0)
  607.      strcat(buildline, " ");
  608.       strcat(buildline, command.get_text());
  609.    }
  610.  
  611.    if(x>1 || buildline[0]!='/')
  612.       sprintf(commandline,"{ %s }", buildline);
  613.    else
  614.       strcpy(commandline, buildline);
  615.    
  616.    Stack::set(Environment::PFont, Font::Currentused, 0.0, commandline);
  617. }
  618.  
  619.  
  620. /* Gives the postscript file describing parameters for the next page */
  621. void Operator::pspage(int, int, float, char *)
  622. {
  623.    Token openbrace;
  624.    if(!openbrace.match("{"))
  625.       Global::files->fatal_error("Expecting '{' after \\pspage statement");
  626.    
  627.    Token filename;
  628.    if(filename.match("}"))
  629.       Global::files->warning(
  630.             "Expecting filename before closing '}' in \\pspage");
  631.  
  632.    Token closebrace;
  633.    if(!closebrace.match("}"))
  634.       Global::files->fatal_error(
  635.          "More than one word before closing '}' in \\pspage");
  636.  
  637.    // Use the new pspage.
  638.    Global::files->use_pspage(filename.get_text());
  639. }
  640.  
  641. void Operator::ref(int, int, float, char *)
  642. {
  643.    Token openbrace;
  644.    if(!openbrace.match("{"))
  645.       Global::files->fatal_error("Expecting '{' after \\ref statement");
  646.    
  647.    Token labelname;
  648.    if(labelname.match("}"))
  649.       Global::files->warning(
  650.             "Expecting label name before closing '}' in \\ref");
  651.  
  652.    Token closebrace;
  653.    if(!closebrace.match("}"))
  654.       Global::files->fatal_error(
  655.          "More than token before closing '}' in \\ref. Sorry, you must rename your label.");
  656.  
  657.    Global::labels->print_ref(labelname.get_text());
  658. }
  659.  
  660. void Operator::replace(int, int, float, char *replacestr)
  661. {
  662.    if(replacestr[0])    // A null string means there is no replacement
  663.       plaintext(replacestr);
  664. }
  665.  
  666. void Operator::setlength(int paramtype, int subtype, float value,
  667.                          char *replacestr)
  668. {
  669.    Length *length;
  670.    length = Global::stack->get_length();
  671.    length->setlength(paramtype, subtype, value, replacestr);
  672. }
  673.  
  674. // Skip the contents of the next brace set
  675. void Operator::skip(int paramtype, int subtype, float value,
  676.             char *replacestr)
  677. {
  678.    Token openbrace;
  679.    if(!openbrace.match("{"))
  680.       Global::files->fatal_error("Missing {");
  681.       
  682.    Token token;
  683.    while(!token.match("}")) {
  684.       token = Token();
  685.       if(token.match("\\end"))
  686.      Operator::skip(paramtype, subtype, value, replacestr);
  687.    }
  688. }
  689.  
  690. void Operator::today(int, int, float, char*)
  691. {
  692.    char buffer[20];
  693.    time_t clock;
  694.    
  695.    time(&clock);
  696.    struct tm *tm = localtime(&clock);
  697.  
  698.    strftime(buffer, 20, "%B", tm);
  699.    Operator::plaintext(buffer);
  700.    strftime(buffer, 20, "%d,", tm);
  701.    if(buffer[0]=='0')
  702.       Operator::plaintext(&buffer[1]);
  703.    else
  704.       Operator::plaintext(buffer);
  705.    strftime(buffer, 20, "%Y", tm);
  706.    Operator::plaintext(buffer);
  707. }
  708.  
  709. void Operator::vspace(int, int, float, char *)
  710. {
  711.    Token openbrace;
  712.    if(!openbrace.match("{"))
  713.       Global::files->fatal_error("Expecting '{' after \\vspace");
  714.    
  715.    float height = Stack::get(Environment::PLength, Length::Parse_Length, "");
  716.    Operator::do_vspace(0, 0, height, "");
  717. }
  718.  
  719. int Operator::isvalid()
  720. {
  721.    return _valid;
  722. }
  723.  
  724. int Operator::is_stealth()
  725. {
  726.    return _stealth;
  727. }
  728.